package com.gitee.wsl.compose.state

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import arrow.core.Either
import com.gitee.wsl.struct.either.toLeft
import com.gitee.wsl.struct.either.toRight
import com.gitee.wsl.compose.use.useBoolean

/**
 * See [https://usehooks.com/useToggle/]
 */
@Composable
fun S.useToggle(initialState: Boolean = false): Pair<Boolean, () -> Unit> {
    var state by remember { mutableStateOf(initialState) }

    fun toggle() {
        state = !state
    }

    return Pair(state, ::toggle)
}

/**
 * 用于在两个状态值间切换的 Hook。
 */
@Composable
fun <T> S.useToggle(
    defaultValue: T? = null,
    reverseValue: T? = null,
): Pair<T?, () -> Unit> {
    // 默认是左值（false）
    val (isLeft, toggle) = useBoolean(true)
    return (if (isLeft) defaultValue else reverseValue) to toggle
}

/**
 * Description:用于在两个状态值间切换的 Hook。为了保证类型信息不消失，使用[Either]作为容器保存；
 * 调用者在使用时根据实际情况调用 [Either.fold] 函数或者其他函数处理；
 */
@Composable
fun <L, R> S.useToggleEither(
    defaultValue: L? = null,
    reverseValue: R? = null,
): Pair<Either<L?, R?>, () -> Unit> {
    // 默认是左值
    val (isLeft, toggle) = useBoolean(true)
    return (if (isLeft) defaultValue.toLeft() else reverseValue.toRight()) to toggle
}

/**
 * 用于方便的切换控制组件的可见性
 */
@Composable
fun S.useToggleVisible(
    isVisible: Boolean = false,
    content: @Composable () -> Unit,
): Pair<@Composable () -> Unit, () -> Unit> {
    val empty: @Composable () -> Unit = {}
    return useToggleVisible(isVisible, content, empty)
}

@Composable
fun S.useToggleVisible(
    isFirst: Boolean = true,
    content1: @Composable () -> Unit,
    content2: @Composable () -> Unit,
): Pair<@Composable () -> Unit, () -> Unit> {
    val (visible, toggle) = useBoolean(isFirst)
    return (if (visible) content1 else content2) to toggle
}